package org.keyory.map_editor.model.default_map;

import it.sauronsoftware.base64.Base64;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;

import org.keyory.map_editor.model.EditableMap;
import org.keyory.map_editor.model.Item;
import org.keyory.map_editor.model.StoreUtil;
import org.keyroy.tag.Tag;
import org.keyroy.tag.XmlSAX;

public class XmlStoreUtil implements StoreUtil {
	private static final String TAG = "MAP.xml";

	@Override
	public void onLoad(File root, EditableMap map) {
		File file = new File(root, TAG);
		if (file.exists()) {
			Tag tag = null;
			try {
				tag = XmlSAX.parseTag(new FileInputStream(file));
			} catch (Exception e) {
			}

			if (tag != null) {
				{
					map.setX(tag.getParameterIntValue("x"));
					map.setY(tag.getParameterIntValue("y"));
					map.setGridWidth(tag.getParameterIntValue("gw"));
					map.setGridHeight(tag.getParameterIntValue("gh"));
				}

				{

					Tag floorSourceTag = tag.getChildTag("fs");
					java.util.List<Tag> tags = floorSourceTag.getChildTagArray("img");
					java.util.List<File> files = new ArrayList<File>();
					for (int i = 0; i < tags.size(); i++) {
						files.add(new File(tag.getParameterValue("src")));
					}

					map.setFloorSource(files);
				}

				{

					Tag itemSourceTag = tag.getChildTag("is");
					java.util.List<Tag> tags = itemSourceTag.getChildTagArray("img");
					java.util.List<File> files = new ArrayList<File>();
					for (int i = 0; i < tags.size(); i++) {
						files.add(new File(tag.getParameterValue("src")));
					}

					map.setItemSource(files);

				}

				{
					Tag floolData = tag.getChildTag("fd");
					if (floolData != null) {
						String dataString = floolData.getParameterValue("data");
						byte[] bs = Base64.decode(dataString.getBytes());
						int[][] data = new int[map.getX()][map.getY()];
						try {
							ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(bs);
							DataInputStream dataInputStream = new DataInputStream(arrayInputStream);
							if (map.getFloorSource().size() < Byte.MAX_VALUE) {
								for (int j = 0; j < map.getY(); j++) {
									for (int i = 0; i < map.getX(); i++) {
										data[i][j] = dataInputStream.read();
									}
								}
							} else if (map.getFloorSource().size() < Short.MAX_VALUE) {
								for (int j = 0; j < map.getY(); j++) {
									for (int i = 0; i < map.getX(); i++) {
										data[i][j] = dataInputStream.readShort();
									}
								}

							} else {
								for (int j = 0; j < map.getY(); j++) {
									for (int i = 0; i < map.getX(); i++) {
										data[i][j] = dataInputStream.readInt();
									}
								}
							}
							dataInputStream.close();
							arrayInputStream.close();
						} catch (Exception e) {
						}

						map.setFloor(data);
					}
				}

				{
					Tag itemDataTag = tag.getChildTag("id");
					java.util.List<Tag> tags = itemDataTag.getChildTagArray("item");
					java.util.List<Item> items = new ArrayList<Item>(tags.size());
					for (int i = 0; i < tags.size(); i++) {
						Tag cTag = tags.get(i);
						Item item = new Item(cTag.getParameterIntValue("src"));
						item.setLocation(cTag.getParameterIntValue("x"), cTag.getParameterIntValue("y"));

						items.add(item);
					}
					map.setItems(items);
				}
			}

		}

	}

	@Override
	public void onSave(File root, EditableMap map) {
		Tag tag = new Tag();

		{
			tag.addParameter("x", map.getX());
			tag.addParameter("y", map.getY());
			tag.addParameter("gw", map.getGridWidth());
			tag.addParameter("gh", map.getGridHeight());
		}

		{
			Tag floorSourceTag = new Tag();
			floorSourceTag.setName("fs");
			floorSourceTag.addParameter("size", map.getFloorSource().size());
			for (int i = 0; i < map.getFloorSource().size(); i++) {
				Tag cTag = new Tag();
				cTag.setName("img");
				cTag.addParameter("src", map.getFloorSource().get(i).getAbsolutePath());
				floorSourceTag.addChild(cTag);
			}

			tag.addChild(floorSourceTag);
		}

		{
			Tag itemSourceTag = new Tag();
			itemSourceTag.setName("is");
			for (int i = 0; i < map.getItemSource().size(); i++) {
				Tag cTag = new Tag();
				cTag.setName("img");
				cTag.addParameter("src", map.getItemSource().get(i).getAbsolutePath());
				itemSourceTag.addChild(cTag);
			}

			tag.addChild(itemSourceTag);

		}

		{
			Tag floolData = new Tag();
			floolData.setName("fd");
			try {
				ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(map.getX() * map.getY());
				DataOutputStream dataOutputStream = new DataOutputStream(arrayOutputStream);
				if (map.getFloorSource().size() < Byte.MAX_VALUE) {
					for (int j = 0; j < map.getY(); j++) {
						for (int i = 0; i < map.getX(); i++) {
							dataOutputStream.write((byte) map.getFloor()[i][j]);
						}
					}

				} else if (map.getFloorSource().size() < Short.MAX_VALUE) {
					for (int j = 0; j < map.getY(); j++) {
						for (int i = 0; i < map.getX(); i++) {
							dataOutputStream.writeShort(map.getFloor()[i][j]);
						}
					}
				} else {
					for (int j = 0; j < map.getY(); j++) {
						for (int i = 0; i < map.getX(); i++) {
							dataOutputStream.writeInt(map.getFloor()[i][j]);
						}
					}
				}
				String dataString = new String(Base64.encode(arrayOutputStream.toByteArray()));
				floolData.addParameter("data", dataString);
				dataOutputStream.close();
				arrayOutputStream.close();
			} catch (Exception e) {
			}

			tag.addChild(floolData);
		}

		{
			Tag itemDataTag = new Tag();
			itemDataTag.setName("id");
			java.util.List<Item> items = map.getItems();
			for (int i = 0; i < items.size(); i++) {
				Item item = items.get(i);
				Tag cTag = new Tag();
				cTag.setName("item");
				cTag.addParameter("x", item.getX());
				cTag.addParameter("y", item.getY());
				cTag.addParameter("src", item.getSource());
				itemDataTag.addChild(cTag);
			}
			tag.addChild(itemDataTag);
		}

		File file = new File(root, TAG);

		try {
			file.createNewFile();
			FileOutputStream fileOutputStream = new FileOutputStream(file);
			fileOutputStream.write(tag.toFormateString().getBytes("UTF-8"));
			fileOutputStream.close();
		} catch (Exception e) {
			// TODO: handle exception
		}

	}
}
